home *** CD-ROM | disk | FTP | other *** search
- Glydo.DocumentManager = Prototype.Class.create(Glydo.EventSource,{
- initialize: function($super) {
- $super();
- this.browsers = new Array();
- this.listeners = new Array();
- this.nextBrowserId = 0;
- this.nextDocumentId = 0;
- // FIXME: fix this, it is not initialized correctly
- this.currentBrowserEntry = null;
- this.cache = new Glydo.DocumentManager.Cache();
- if (Glydo.Prefs.offline_source_dir) {
- this.offlineSource = new Glydo.DocumentManager.OfflineSource();
- }
- if (Glydo.Prefs.offline_log_dir &&
- (Glydo.Prefs.offline_log_with_offline_source || !this.offlineSource)) {
- this.offlineLog = new Glydo.DocumentManager.OfflineLog();
- }
- },
-
- onMainDocDomLoad: function(browser,doc) {
- if (this.containsDocument(doc)) {
- return;
- }
- var browserEntry = this.findOrCreateBrowserEntry(browser);
- var newDocumentEntry = new Glydo.DocumentManager.DocumentEntry(browserEntry,doc,this.nextDocumentId++);
- browserEntry.onNewDocument(newDocumentEntry);
- this.fire("onNewDocument",newDocumentEntry);
- if (this.currentBrowserEntry === browserEntry) {
- this.fire("onCurrentDocumentChanged",newDocumentEntry);
- }
- this.fireStateChange();
- },
-
- onTabOpen: function(browser) {
- },
-
- onTabClose: function(browser) {
- var found = this.findBrowserIndex(browser);
- if (found !== null) {
- this.browsers.splice(found,1);
- }
- },
-
- onTabSelect: function(browser) {
- this.currentBrowserEntry = this.findOrCreateBrowserEntry(browser);
- this.fire("onCurrentDocumentChanged",this.currentBrowserEntry.currentDocumentEntry);
- this.fire("onCurrentProcessedDocumentChanged",this.currentBrowserEntry.currentProcessedDocumentEntry);
- },
-
- containsDocument: function(doc) {
- for (var i = 0; i < this.browsers.length; ++i) {
- if (this.browsers[i].containsDocument(doc)) {
- return true;
- }
- }
- return false;
- },
-
- findBrowserIndex: function(browser) {
- for (var i = 0; i < this.browsers.length; ++i) {
- if (this.browsers[i].browser === browser) {
- return i;
- }
- }
- return null;
- },
-
- findBrowserEntry: function(browser) {
- var found = this.findBrowserIndex(browser);
- if (found === null) {
- return null;
- }
- return this.browsers[found];
- },
-
- findOrCreateBrowserEntry: function(browser) {
- for (var i = 0; i < this.browsers.length; ++i) {
- if (this.browsers[i].browser === browser) {
- return this.browsers[i];
- }
- }
- var browserEntry = new Glydo.DocumentManager.BrowserEntry(this,browser,this.nextBrowserId++);
- this.browsers.push(browserEntry);
- return browserEntry;
- },
-
- getCurrentDocument: function() {
- if (this.currentBrowserEntry) {
- if (this.currentBrowserEntry.currentDocumentEntry) {
- return this.currentBrowserEntry.currentDocumentEntry;
- }
- }
- return null;
- },
-
- getCurrentProcessedDocument: function() {
- if (this.currentBrowserEntry) {
- if (this.currentBrowserEntry.currentProcessedDocumentEntry) {
- return this.currentBrowserEntry.currentProcessedDocumentEntry;
- }
- }
- return null;
- },
-
- isCurrentDocument: function(documentEntry) {
- return this.getCurrentDocument() === documentEntry;
- },
-
- isCurrentBrowser: function(browserEntry) {
- return this.currentBrowserEntry === browserEntry;
- },
-
- isCurrentProcessedDocument: function(documentEntry) {
- return this.getCurrentProcessedDocument() === documentEntry;
- },
-
- fireStateChange: function(browser) {
- this.fire('onDocumentManagerStateChange');
- },
-
- containsValidDocuments: function() {
- var nBrowsers = this.browsers.length;
- for (var i = 0; i < nBrowsers; ++i) {
- if (this.browsers[i].currentProcessedDocumentEntry) {
- return true;
- }
- }
- return false;
- },
-
- containsUnrenderedValidDocuments: function() {
- var nBrowsers = this.browsers.length;
- for (var i = 0; i < nBrowsers; ++i) {
- if (this.browsers[i].currentProcessedDocumentEntry && !d.rendered) {
- return true;
- }
- }
- return false;
- },
-
- isProcessing: function() {
- if (!this.currentBrowserEntry) {
- return false;
- }
- if (!this.currentBrowserEntry.currentDocumentEntry) {
- return false;
- }
- return !this.currentBrowserEntry.currentDocumentEntry.isDone();
- },
-
- isCurrentDocumentValid: function() {
- if (!this.currentBrowserEntry) {
- return false;
- }
- if (!this.currentBrowserEntry.currentDocumentEntry) {
- return false;
- }
- return this.currentBrowserEntry.currentDocumentEntry.isDone();
- },
-
- isTrackableURL: function(documentURI)
- {
- return Glydo.DocumentManager.TRACKABLE_URL_PATTERN.test(documentURI);
- }
-
- });
-
- /////////////////////////////////////////////////////////////////////////
- // BrowserEntry class contains the state of all documents
- // in the history of browser. Documents are added as the browser
- // traverses documents, and removed after both the following take place:
- // 1. The document was unloaded
- // 2. The document is old enough to discard
- /////////////////////////////////////////////////////////////////////////
-
- Glydo.DocumentManager.BrowserEntry = Prototype.Class.create({
- initialize: function(manager,browser,id) {
- this.manager = manager;
- this.browser = browser;
- this.id = id;
- // this.oldDocs = new Array();
- this.currentDocumentEntry = null;
- this.currentProcessedDocumentEntry = null;
- },
-
- getCache: function() {
- return this.manager ? this.manager.cache : null;
- },
-
- getOfflineSource: function() {
- return this.manager ? this.manager.offlineSource : null;
- },
-
- getOfflineLog: function() {
- return this.manager ? this.manager.offlineLog : null;
- },
-
- containsDocument: function(doc) {
- if (this.currentDocumentEntry === doc) {
- return true;
- }
- // for (var i = 0; i < this.oldDocs.length; ++i) {
- // if (this.oldDocs[i].document === doc) {
- // return true;
- // }
- // }
- return false;
- },
-
- onNewDocument: function(docEntry) {
-
- if (this.currentDocumentEntry) {
- this.currentDocumentEntry.cancelProcessing();
- }
- this.currentDocumentEntry = docEntry;
- this.currentDocumentEntry.startProcessing();
- },
-
- isTrackableURL: function(documentURI) {
- return this.manager.isTrackableURL(documentURI);
- },
-
- onDoneProcessing: function(docEntry) {
- docEntry.logRequest();
- if (!docEntry.cancelled) {
- if (docEntry === this.currentDocumentEntry) {
-
- if (docEntry.hasRecommendations()) {
-
- } else if (docEntry.state == 'SUCCEEDED') {
-
- } else {
-
- }
- this.currentProcessedDocumentEntry = docEntry;
- if (this.manager.isCurrentBrowser(this)) {
- this.manager.fire("onCurrentProcessedDocumentChanged",docEntry);
- }
- }
- }
- this.manager.fireStateChange();
- },
-
- });
-
- /////////////////////////////////////////////////////////////////////////
- //DocumentEntry class contains the state of a specific document
- //loaded in a browser.
- /////////////////////////////////////////////////////////////////////////
-
- Glydo.DocumentManager.DocumentEntry = Prototype.Class.create({
- initialize: function(manager,doc,id) {
- this.manager = manager;
- this.document = doc;
- this.id = id;
- this.recommendations = null;
- this._hasRecommendations = false;
- this.state = "CREATED";
- this.cancelled = false;
- this.rendered = false;
- this.requestTime = null;
- this.responseTime = null;
- this.resultSource = null;
- this.fromCache = false;
- this.extractionTask = null;
- this.viewSpecificData = {};
- },
-
- getViewSpecificData: function(key) {
- return this.viewSpecificData[key];
- },
-
- setViewSpecificData: function(key,value) {
- this.viewSpecificData[key] = value;
- },
-
- getCache: function() {
- return this.manager ? this.manager.getCache() : null;
- },
-
- getOfflineSource: function() {
- return this.manager ? this.manager.getOfflineSource() : null;
- },
-
- getOfflineLog: function() {
- return this.manager ? this.manager.getOfflineLog() : null;
- },
-
- cancelProcessing: function() {
- if (!this.isDone()) {
- this.cancelled = true;
- if (this.extractionTask) {
- this.extractionTask.cancel();
- }
- }
- },
-
- startProcessing: function() {
-
- this.startProcessingTime = new Date();
-
- if (!this.document.documentURI) {
- this.state = "SUCCEEDED";
- this.manager.onDoneProcessing(this);
- return;
- }
-
-
-
- // Check for an appropriate result in the cache
- var cached = this.getCache().lookup(this.document.documentURI);
- if (cached) {
-
- this.loadFromCachedResult(cached);
- return;
- }
-
- // Check for an offline source
- if (this.getOfflineSource()) {
- var offline = this.getOfflineSource().lookup(this.document.documentURI);
- if (offline) {
-
- this.loadFromOfflineResult(offline);
- return;
- }
-
- }
-
- if (!this.manager.isTrackableURL(this.document.documentURI)) {
- this.state = "SUCCEEDED";
- this.manager.onDoneProcessing(this);
- return;
- }
-
- if (Glydo.Utils.isPrivateBrowsingEnabled()) {
- this.state = "SUCCEEDED";
- this.manager.onDoneProcessing(this);
- return;
- }
-
- this.resultSource = "server";
- this.fromCache = false;
-
- this.contextItems = [];
- this.contextExtractionTask = Glydo.CONTEXT_EXTRACTOR.extract(this.document,{
- onContextItem: Prototype.F.bind(this.onContextItemExtracted,this),
- onCompleted: Prototype.F.bind(this.onContextExtractionDone,this),
- onFailure: Prototype.F.bind(this.onFailure,this),
- });
- },
-
- onFailure: function(reason) {
- this.state = "FAILED";
- this.error = reason;
- this.manager.onDoneProcessing(this);
- },
-
- onAjaxFailure: function(response) {
- var reason = response ? response.responseText : "Communication problem";
- if (!reason) {
- reason = "Communication problem";
- }
- this.onFailure(reason);
- },
-
- onContextItemExtracted: function(contextItem) {
- if (typeof(contextItem) == "object" && contextItem != null) {
- // Generate a unique id for the context item and store it
- var id = Glydo.Utils.uuid1();
- this.contextItems[id] = contextItem;
- }
- },
-
- encodeContextInfo: function() {
- var items = [];
- items.__itemName = "item";
- for (var id in this.contextItems) {
- var c = this.contextItems[id];
- c["@id"] = id;
- items.push(c);
- }
- if (items.length == 0) {
- return null;
- }
- items = ({
- "context": {
- "page": {
- "title":this.document.title
- },
- "items": items
- }
- });
- var ctxDoc = document.implementation.createDocument("","",null);
- Glydo.Utils.toXml(ctxDoc,items);
- var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"].createInstance(Components.interfaces.nsIDOMSerializer);
- return serializer.serializeToString(ctxDoc);
- },
-
- onContextExtractionDone: function(contextInfo) {
- // Check for cancellation
- if (this.cancelled) {
- this.state = "FAILED";
- this.error = "Cancelled";
- this.manager.onDoneProcessing();
- return;
- }
- var encodedContextInfo = this.encodeContextInfo();
- if (encodedContextInfo == null) {
- this.onFailure("No context information");
- return;
- }
- // Create request parameters
- var params = new Object();
- params.clientId = Glydo.CLIENT_INFO.clientId;
- params.action = "get";
- params.format = "json";
- params.url = this.document.documentURI;
- params.rawContextInfo = encodedContextInfo;
- //
- var e = Glydo.Prefs.engines;
- if (e.length > 0) {
- params.engines = e.join(",");
- }
- var p = Glydo.Prefs.publishers;
- if (p.length > 0) {
- params.publishers = p.join(",");
- }
- params.appId = Glydo.CLIENT_INFO.appId;
- if (Glydo.Prefs.server_trace) {
- params.useTrace = 1;
- }
-
-
- // Create a new AJAX request for the new location
- this.ajax_request = new Prototype.Ajax.Request(
- Glydo.Prefs.server_url, {
- method: 'post',
- parameters: params,
- onSuccess: Prototype.F.bind(this.onGetRecommendationsSuccess,this),
- onFailure: Prototype.F.bind(this.onAjaxFailure,this)
- });
- this.requestTime = new Date();
-
- this.state = "GETTING_RECOMMENDATIONS";
- },
-
- onGetRecommendationsSuccess: function(response) {
- if (!response || (response.status == 0)) {
- this.onAjaxFailure(response);
- return;
- }
- this.responseTime = new Date();
- if (this.cancelled) {
- this.state = "FAILED";
- this.error = "Cancelled";
- this.manager.onDoneProcessing(this);
- return;
- }
-
- //
- this.recommendations = response.responseJSON;
- this.state = "SUCCEEDED";
- if (this.getOfflineLog()) {
- this.getOfflineLog().log(this);
- }
- var valid = this.processRecommendationsPreCacheSave();
- if (valid) {
- if (!this.fromCache) {
- this.getCache().save(this);
- }
- this.processRecommendationsPostCacheSave();
- }
- this.manager.onDoneProcessing(this);
- },
-
- processRecommendationsPreCacheSave: function() {
- if (!this.recommendations) {
- return false;
- }
-
- if (this.recommendations.documentAnalysis) {
- var contextAnnotations = this.recommendations.documentAnalysis.contextAnnotations;
- if (contextAnnotations && Prototype.O.isArray(contextAnnotations)) {
- var nca = contextAnnotations.length;
- for (var ica = 0; ica < nca; ++ica) {
- var ca = contextAnnotations[ica];
- var id = ca["id"];
-
- this.contextItems[id].annotation = ca;
- }
- }
- }
-
- var recSet = this.recommendations.recommendationsSet;
- if (recSet === undefined) {
-
- return false;
- }
-
- var recSetId = recSet.id;
- if (recSetId === undefined) {
-
- return false;
- }
-
- var recs = recSet.recommendations;
- if (recs == undefined) {
-
- return false;
- }
-
- var nrecs = Math.min(recs.length,Glydo.Prefs.max_recs_from_server_to_process);
-
- recs.splice(nrecs);
-
- for (var i = 0; i < nrecs; ++i) {
- var rec = recs[i];
- rec.recSetId = recSetId;
- rec.globalId = rec.recSetId + "_" + rec.id;
- rec.receivedTime = this.responseTime;
- rec.viewSpecificInfo = {};
- this.markRecReceived(rec);
- this.setupImageLoaders(rec);
- this._hasRecommendations = true;
- }
-
- // This is a bit of a hack. We compute here virtual recommendations for
- // "info" recs with identical terms
-
- // FIXME: For now we do this by title, but it's wrong. Missing
- // required data from the server
- var infoRecsByTerm = {};
- for (var i = 0; i < nrecs; ++i) {
- var rec = recs[i];
- }
-
- return true;
- },
-
- setupImageLoaders: function(rec) {
- rec.imageLoaders = {};
- this.loadRecommendationThumbnails(rec);
- this.loadRecommendationFavicon(rec);
- },
-
- loadRecommendationImageInternal: function(rec,key,thumbnailGroups,targetWidth,targetHeight,options) {
- if (!rec.imageLoaders[key]) {
- rec.imageLoaders[key] = new Glydo.BestThumbnailLoader(
- targetWidth, targetHeight,
- thumbnailGroups, options);
- }
- },
-
- loadRecommendationThumbnails: function(rec) {
- var thumbnailGroups;
- // thumbnailGroups = [rec.thumbnails].concat([[{
- // width: 80,
- // height: 60,
- // lazy: true,
- // url: Glydo.gApp.generateThumbnailServiceURL(rec)
- // }]]);
- thumbnailGroups = [rec.thumbnails];
- if (rec.contentType == "video") {
- this.loadRecommendationImageInternal(rec,"thumbnail-or-capture:120x90",
- thumbnailGroups,120,90);
- } else if (rec.contentType == "info") {
- this.loadRecommendationImageInternal(rec,"thumbnail-or-capture:60x60",
- thumbnailGroups,60,60);
- } else if (rec.contentType == "twitter") {
- if (rec.thumbnails && rec.thumbnails.length > 0) {
- this.loadRecommendationImageInternal(rec,"thumbnail:48x48",
- [rec.thumbnails],48,48);
- }
- } else {
- this.loadRecommendationImageInternal(rec,"thumbnail-or-capture:80x60",
- thumbnailGroups,80,60);
- }
- // Load origin thumbnails as well
- if (rec.origin) {
- this.loadRecommendationImageInternal(rec,"origin:thumbnail:90x40",[rec.origin.thumbnails],90,40,{
- validation: Glydo.DocumentManager.VALIDATE_ORIGIN_IMAGE_FUNC
- });
- }
- },
-
- loadRecommendationFavicon: function(rec) {
- var imageKey = "favicon:16x16";
- var thumbnailGroups = Glydo.Utils.getFaviconURLs(rec.url,rec.website).map(
- function(url) {
- return ([{
- width: 16,
- height: 16,
- url: url
- }]);
- });
-
- this.loadRecommendationImageInternal(rec,imageKey,thumbnailGroups,16,16);
- },
-
- processRecommendationsPostCacheSave: function() {
- var recSet = this.recommendations.recommendationsSet;
- var recs = recSet.recommendations;
-
- var nrecs = recs.length;
-
- for (var i = 0; i < nrecs; ++i) {
- var rec = recs[i];
- rec.documentEntry = this;
- if (rec.contextItemId) {
- rec.contextItem = this.contextItems[rec.contextItemId];
- }
- }
- },
-
- loadFromOfflineResult: function(result) {
- this.resultSource = "offline";
- this.onGetRecommendationsSuccess(result);
- },
-
- loadFromCachedResult: function(result) {
- for (var property in result) {
- this[property] = result[property];
- }
- if (!this.resultSource) {
- this.resultSource = "cache";
- }
- this.fromCache = true;
- this.processRecommendationsPostCacheSave();
- this.state = "SUCCEEDED";
- this.manager.onDoneProcessing(this);
- },
-
- selectRecommendations: function(filter) {
- if (!this.recommendations || !this.recommendations.recommendationsSet || !this.recommendations.recommendationsSet.recommendations) {
- return [];
- }
- if (Prototype.O.isArray(filter)) {
- return filter;
- }
- var de = this;
- var result = this.recommendations.recommendationsSet.recommendations;
- if (filter.condition !== undefined) {
- // First, filter the recommendations
- var filterFunc;
- if (Prototype.O.isFunction(filter.condition)) {
- filterFunc = filter.condition;
- } else {
- filterFunc = function(rec) {
- for (key in filter.condition) {
- var cond = filter.condition[key];
- if (Prototype.O.isFunction(cond)) {
- return cond.call(de,rec[key])
- } else {
- if (!Prototype.O.isArray(cond)) {
- cond = [cond];
- }
- if (cond.indexOf(rec[key]) === -1) {
- return false;
- }
- }
- }
- return true;
- };
- }
- result = result.filter(filterFunc,this);
- }
- // Next, sort them
- if (filter.orderBy !== undefined) {
- if (Prototype.O.isFunction(filter.orderBy)) {
- result = Prototype.A.sortBy(result,filter.orderBy);
- } else {
- var orderBy = Prototype.O.isArray(filter.orderBy) ? filter.orderBy : [filter.orderBy];
- result.sort(function(rec1,rec2) {
- var comp = 0;
- orderBy.every(function(key) {
- var desc = Prototype.S.startsWith(key,"-");
- if (desc || Prototype.S.startsWith(key,"+")) {
- key = key.substring(1);
- }
- var v1 = rec1[key];
- var v2 = rec2[key];
- if (v1 < v2) {
- comp = desc ? 1 : -1;
- return false;
- } else if (v1 > v2) {
- comp = desc ? -1 : 1;
- return false;
- }
- return true;
- });
- return comp;
- });
- }
- }
-
- // Finally, truncate the result if necessary
- if (filter.limit !== undefined) {
- result = result.slice(0,filter.limit);
- }
- return result;
- },
-
- isDone: function() {
- return this.isSucceeded() || this.isFailed();
- },
-
- isProcessed: function() {
- return this.isDone() && !this.cancelled;
- },
-
- isSucceeded: function() {
- return this.state == 'SUCCEEDED';
- },
-
- isFailed: function() {
- return this.state == 'FAILED';
- },
-
- hasRecommendations: function() {
- return this.isDone() && this._hasRecommendations;
- },
-
- markRendered: function() {
- this.rendered = true;
- this.manager.manager.fireStateChange();
- },
-
- getRecSetId: function() {
- if (this.recommendations &&
- this.recommendations.recommendationsSet &&
- this.recommendations.recommendationsSet.id) {
- return this.recommendations.recommendationsSet.id;
- }
- return null;
- },
-
- logRequest: function() {
- if (!this.requestTime || (this.resultSource !== "server")) {
- return;
- }
-
- var recSetId = this.getRecSetId();
-
-
- if (!this.fromCache) {
- Glydo.LOGGING_DB.logRecsRequest(
- this.requestTime,
- this.responseTime,
- recSetId,
- this.cancelled);
- } else {
- // Log the cached rec request hit
- Glydo.LOGGING_DB.logCachedRecsReqHit(
- this.startProcessingTime,
- recSetId);
- }
-
- },
-
- markRecReceived: function(rec) {
- if (!this.requestTime || this.resultSource !== "server") {
- return;
- }
-
- Glydo.LOGGING_DB.markAckedRecAsReceived(rec.url,this.responseTime);
- },
-
- });
-
- /////////////////////////////////////////////////////////////////////////
- //Cache class
- /////////////////////////////////////////////////////////////////////////
- Glydo.DocumentManager.Cache = Prototype.Class.create({
- initialize: function() {
- this.cacheEntryListHead = new Glydo.DocumentManager.CacheEntry();
- this.cacheLookupTable = {};
- this.size = 0;
- },
-
- lookup: function(url) {
-
- var cacheEntry = this.cacheLookupTable[url];
- if (!cacheEntry) {
-
- return null;
- }
- var now = Date.now();
- if (now - cacheEntry.createdAt > Glydo.Prefs.cache_max_age_millis) {
-
- this.removeEntry(cacheEntry);
- return null;
- }
-
- this.markAsJustUsed(cacheEntry);
- return cacheEntry.result;
- },
-
- // save should only be called when we have a really new result
- // to cache. It should not be called for old cache results.
- save: function(documentEntry) {
- var url = documentEntry.document.documentURI;
- // Remove any old cache entry if it exists
- // We do this so that a caller may overwrite the cache entry
- // with new data
- var oldCacheEntry = this.cacheLookupTable[url];
- if (oldCacheEntry) {
- this.removeEntry(oldCacheEntry);
- }
-
- var m = Math.max(Glydo.Prefs.cache_max_entries,0);
- while (this.size > m) {
-
- this.removeLeastRecentlyUsedEntry();
- }
- if (this.size == m && m > 0) {
-
- this.removeLeastRecentlyUsedEntry();
- }
- if (this.size < m) {
- var cacheEntry = new Glydo.DocumentManager.CacheEntry(url,documentEntry);
- this.addEntryAsJustUsed(cacheEntry);
- }
- },
-
- addEntryAsJustUsed: function(cacheEntry) {
- this.cacheEntryListHead.insertAsNext(cacheEntry);
- cacheEntry.markAsJustUsed();
- this.cacheLookupTable[cacheEntry.url] = cacheEntry;
- this.size++;
- },
-
- removeEntry: function(cacheEntry) {
- cacheEntry.remove();
- delete this.cacheLookupTable[cacheEntry.url];
- this.size--;
- },
-
- removeLeastRecentlyUsedEntry: function() {
- if (this.cacheEntryListHead.prev !== this.cacheEntryListHead) {
- this.removeEntry(this.cacheEntryListHead.prev);
- }
- },
-
- markAsJustUsed: function(cacheEntry) {
- this.removeEntry(cacheEntry);
- this.addEntryAsJustUsed(cacheEntry);
- },
-
- });
-
- /////////////////////////////////////////////////////////////////////////
- //CacheEntry class
- /////////////////////////////////////////////////////////////////////////
- Glydo.DocumentManager.CacheEntry = Prototype.Class.create({
- initialize: function(url,result) {
- // Create the entry as a single node in a list
- this.next = this;
- this.prev = this;
- if (result) {
- this.url = url;
- this.createdAt = Date.now();
- this.result = {};
- this.CACHABLE_PROPERTIES.forEach(function(property) {
- this.result[property] = result[property];
- },this);
- this.markAsJustUsed();
- }
- },
-
- markAsJustUsed: function() {
- this.lastUsedAt = Date.now();
- },
-
- remove: function() {
- var prev = this.prev;
- var next = this.next;
- prev.next = next;
- next.prev = prev;
- },
-
- insertAsNext: function(entry) {
- var next = this.next;
- this.next = entry;
- next.prev = entry;
- entry.next = next;
- entry.prev = this;
- },
-
- CACHABLE_PROPERTIES: ["recommendations","resultSource","_hasRecommendations","requestTime","responseTime","contextItems"]
-
- });
-
- /////////////////////////////////////////////////////////////////////////
- //OfflineSource class represents an offline recommendations source
- /////////////////////////////////////////////////////////////////////////
- Glydo.DocumentManager.OfflineSource = Prototype.Class.create({
- initialize: function() {
- this.responses = {};
- var sourceDir = Glydo.DirIO.get("ProfD");
- sourceDir.append("glydo");
- sourceDir.append("offline_sources");
- sourceDir.append(Glydo.Prefs.offline_source_dir);
-
- if (!sourceDir.exists()) {
-
- return;
- }
- var entries = sourceDir.directoryEntries;
- while (entries.hasMoreElements()) {
- var entry = entries.getNext();
- entry = entry.QueryInterface(Components.interfaces.nsIFile);
- if (entry.isFile()) {
-
- var entryStr = Glydo.FileIO.read(entry,"UTF-8");
- var entryObj = Prototype.S.decodeJSON(entryStr);
- this.responses[entryObj.url] = entryObj.response;
- }
- }
- },
-
- lookup: function(url) {
-
- var response = this.responses[url];
- if (!response) {
- return null;
- }
- return ({
- status: 200,
- responseJSON: response
- });
- }
- });
-
- /////////////////////////////////////////////////////////////////////////
- //OfflineSource class represents an offline logging target
- // for recommendation results
- /////////////////////////////////////////////////////////////////////////
- Glydo.DocumentManager.OfflineLog = Prototype.Class.create({
- initialize: function() {
- var logDir = Glydo.DirIO.get("ProfD");
- logDir.append("glydo");
- logDir.append("offline_logs");
- Glydo.DirIO.create(logDir);
- logDir.append(Glydo.Prefs.offline_log_dir);
- Glydo.DirIO.create(logDir);
- this.logDir = logDir;
-
- },
-
- log: function(documentEntry) {
-
- var file = this.logDir.clone();
- var host = Glydo.Utils.getURLHost(documentEntry.document.documentURI);
- file.append(host + ".json");
- file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
-
- var contentsObj = ({
- url: documentEntry.document.documentURI,
- response: documentEntry.recommendations
- });
- var contents = Prototype.O.toJSON(contentsObj);
- if (Glydo.FileIO.write(file,contents,null,"UTF-8")) {
-
- } else {
-
- }
- }
- });
-
- // CONSTANTS
- Glydo.DocumentManager.TRACKABLE_URL_PATTERN = new RegExp("^http://");
- Glydo.DocumentManager.DEFAULT_RECOMMENDATION_ORDER = {
- maxRecommendations: 20
- };
-
- Glydo.DocumentManager.ORIGIN_DOMAINS_WITH_PROBLEMATIC_IMAGES = ({
- "shopping.com": true,
- "bizrate.com": true
- });
-
- Glydo.DocumentManager.VALIDATE_ORIGIN_IMAGE_FUNC = function(image) {
- if (!Glydo.DocumentManager.ORIGIN_DOMAINS_WITH_PROBLEMATIC_IMAGES[Glydo.Utils.getHighLevelDomainName(this.url).toLowerCase()]) {
- return true;
- }
- if (image.naturalWidth != null &&
- (image.naturalWidth < 10 ||
- (this.width != null && this.width > 0 && this.width != image.naturalWidth))) {
- return false;
- }
- if (image.naturalHeight != null &&
- (image.naturalHeight < 10 ||
- (this.height != null && this.height > 0 && this.height != image.naturalHeight))) {
- return false;
- }
- return true;
- };
-
-